package com.healthcarex.hip.saas.common.util.map;


import com.healthcarex.hip.saas.common.constant.CommonConstant;
import com.healthcarex.hip.saas.common.util.MapArrayInfo;
import com.healthcarex.hip.saas.common.util.Pair;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;


/**
 * @version 1.0
 * @created 18-三月-2014 16:39:54
 */
public class MapUtil {
    public enum MapProcessType {
        ADD, REPLACE, REINIT_ARRAY
    }

    private static final String RESERVED_MAP_VALUE = "$reserved_key$";

    /**
     *
     */
    private MapUtil() {
    }

    /**
     * 从指定的路径中取得Map中的元素
     * <p>
     * 不保证返回对象是Map中的引用，因此修改返回对象的内容不保证修改Map中的对应元素
     *
     * @param path
     * @param message
     * @return Object 不保证返回对象是Map中的对象的引用(目前情况是数组对象(不包含数组中的每一个元素)、简单类型都不是Map中的引用)
     */
    public static Object getValue(String path, Map<String, Object> message) {
        return getValue(path, message, true);
    }

    /**
     * @param path
     * @param message
     * @return
     */
    @SuppressWarnings("unchecked")
    public static int removeKey(String path, Map<String, Object> message) {
        Map<String, Object> retMap = (Map<String, Object>) getValue(path,
                message, false);

        if (retMap == null) {
            return 0;
        }

        Set<Entry<String, Object>> retSet = retMap.entrySet();

        // 删除的key中包含根节点，清空map
        if (retSet.contains("")
                || retSet.contains(CommonConstant.KEY_SEPARATOR)) {
            message.clear();
            return 1;
        }

        int count = 0;
        for (Entry<String, Object> entry : retSet) {
            String key = entry.getKey();
            Map<String, Object> parent = (Map<String, Object>) getParent(key,
                    message);

            if (parent != null) {
                key = getLastKey(key);

                if (StringUtils.isEmpty(key)) {
                    message.clear();
                    return 1;
                }

                parent.remove(key);
                count++;
            }
        }

        return count;
    }

    /**
     * @param path
     * @param message
     * @return
     */
    @SuppressWarnings("unchecked")
    public static int removeValue(String path, Map<String, Object> message) {
        Map<String, Object> retMap = (Map<String, Object>) getValue(path,
                message, true);

        if (retMap == null) {
            return 0;
        }

        Set<Entry<String, Object>> retSet = retMap.entrySet();

        // 删除的key中包含根节点，删除根节点对应的值
        if (retSet.contains("")
                || retSet.contains(CommonConstant.KEY_SEPARATOR)) {
            message.clear();
            return 1;
        }

        int count = 0;
        for (Entry<String, Object> entry : retSet) {
            String key = entry.getKey();
            Map<String, Object> parent = (Map<String, Object>) getParent(key,
                    message);

            if (parent != null) {
                key = getLastKey(key);

                if (StringUtils.isEmpty(key)) {
                    message.clear();
                    return 1;
                }

                parent.put(key, null);
                count++;
            }
        }

        return count;
    }

    /**
     * @param fullPath
     * @param message
     * @return
     */
    private static Object getParent(String fullPath, Map<String, Object> message) {
        String parentPath = getParentPath(fullPath);
        return StringUtils.isEmpty(parentPath) ? null : MapUtil.getValue(
                parentPath, message, false);
    }

    /**
     * @param fullPath
     * @return
     */
    public static String getParentPath(String fullPath) {
        String parentPath = removeEndingSeparator(fullPath);
        int index = parentPath.lastIndexOf(CommonConstant.KEY_SEPARATOR);
        return index > 0 ? parentPath.substring(0, index) : "/";
    }

    /**
     * @param fullPath 最后一级路径不包含数组下标
     * @return
     */
    private static String getLastKey(String fullPath) {
        String parentPath = removeEndingSeparator(fullPath);
        int index = parentPath.lastIndexOf(CommonConstant.KEY_SEPARATOR);
        return index >= 0 ? parentPath.substring(index + 1) : parentPath;
    }

    /**
     * @param path
     * @param message
     * @param splitArrayLeaf 控制路径的最后一级为数组时，数组元素作为整体对象返回、还是拆分成多个key-value项返回
     *                       true:数组元素拆分成多个key
     *                       -value项返回(在返回的Map中，数组的每条记录作为一个key-value对:(key[index],value))
     *                       false:数组元素作为整体对象返回(在返回的Map中，整个数组作为一个value)
     * @return
     */
    private static Object getValue(String path, Map<String, Object> message,
                                   boolean splitArrayLeaf) {
        if (StringUtils.isNotEmpty(path) && message != null) {
            // boolean absolutePath = isAbsolutePath(path);
            Map<String, Object> mapValue = new HashMap<String, Object>();
            MapUtil.processMapContentForValue(message, mapValue, path, "",
                    path, false, splitArrayLeaf);

            return mapValue;
        }

        return null;
    }

    /**
     * ---following are supported :
     * <p>
     * "/key/key/key"
     * <p>
     * "//key/key"
     * <p>
     * "/key/key//key/key//key"
     * <p>
     * "/key/key[0]/key//key"
     * <p>
     * ---Not support
     * <p>
     * array[][]
     *
     * @param content        要解析的对象
     * @param mapValue       返回的结果
     * @param orgPath        要解析的路径的原始值
     * @param curPath        content对象对应的路径
     * @param toResolvePath  正在解析的路径
     * @param allPathFlag    解析父路径的过程中是否包含"//"字符串
     * @param splitArrayLeaf 控制路径的最后一级为数组时，数组元素作为整体对象返回、还是拆分成多个key-value项返回
     *                       true:数组元素拆分成多个key
     *                       -value项返回(在返回的Map中，数组的每条记录作为一个key-value对:(key[index],value))
     *                       false:数组元素作为整体对象返回(在返回的Map中，整个数组作为一个value)
     */
    private static void processMapContentForValue(Object content,
                                                  Map<String, Object> mapValue, String orgPath, String curPath,
                                                  String toResolvePath, boolean allPathFlag, boolean splitArrayLeaf) {

        // no content
        if (content == null) {
            return;
        }

        // path resolved
        if (StringUtils.isEmpty(removeBeginningSeparator(toResolvePath))) {
            mapValue.put(curPath, content);
            return;
        }

        if (content instanceof Map) {
            Map<String, Object> curContent = (Map<String, Object>) content;
            // int index =
            // toResolvePath.indexOf(CommonConstant.KEY_SEPARATOR);
            // 要解析的路径中是否以"//"开头
            boolean isAllPathBeginning = isAllPath(toResolvePath);

            String tmpToResolvePath = removeBeginningSeparator(toResolvePath);
            int nextSeperatorIndex = tmpToResolvePath
                    .indexOf(CommonConstant.KEY_SEPARATOR);
            String curKey = nextSeperatorIndex > 0 ? tmpToResolvePath
                    .substring(0, nextSeperatorIndex) : tmpToResolvePath;
            int arrayIndex = getArrayIndex(curKey);
            curKey = arrayIndex >= 0 ? curKey.substring(0,
                    curKey.indexOf(CommonConstant.ARRAY_INDEX_BEGIN)) : curKey;
            Object childContent = curContent.get(curKey);

            if (isArray(childContent)) {
                List<Object> curChildContent = getArray(childContent);

                if (arrayIndex >= 0) {
                    if (arrayIndex < curChildContent.size()) {
                        processArrayContent(mapValue, curChildContent,
                                arrayIndex, nextSeperatorIndex, allPathFlag,
                                isAllPathBeginning, orgPath, toResolvePath,
                                tmpToResolvePath, curPath, curKey,
                                splitArrayLeaf);
                    } else {
                        // TODO
                        // logger.debug(MessageFormat.format("ERROR : index {} overflow",
                        // arrayIndex));
                    }
                } else {
                    for (int i = 0; i < curChildContent.size(); i++) {
                        processArrayContent(mapValue, curChildContent, i,
                                nextSeperatorIndex, allPathFlag,
                                isAllPathBeginning, orgPath, toResolvePath,
                                tmpToResolvePath, curPath, curKey,
                                splitArrayLeaf);
                    }
                }
            } else if (arrayIndex >= 0) {
                if (!isAllPathBeginning && !allPathFlag) {
                    // Non array & array index >= 0
                    // TODO
                    // logger.debug(MessageFormat.format("ERROR : Invalid index {} for non array",
                    // arrayIndex));
                } else {
                    if (isAllPathBeginning) {
                        for (String key : curContent.keySet()) {
                            processMapContentForValue(curContent.get(key),
                                    mapValue, toResolvePath,
                                    joinPath(curPath, key), toResolvePath,
                                    true, splitArrayLeaf);
                        }
                    }

                    if (allPathFlag) {
                        for (String key : curContent.keySet()) {
                            processMapContentForValue(curContent.get(key),
                                    mapValue, orgPath, joinPath(curPath, key),
                                    orgPath, true, splitArrayLeaf);
                        }
                    }
                }
            } else {
                // Non array
                if (isAllPathBeginning) {
                    // Beginning with "//"
                    // current path to match toResolvePath
                    processMapContentForValue(
                            childContent,
                            mapValue,
                            null,
                            joinPath(curPath, curKey),
                            nextSeperatorIndex > 0 ? tmpToResolvePath
                                    .substring(nextSeperatorIndex) : null,
                            false, splitArrayLeaf);

                    // child path to match toResolvePath
                    for (String key : curContent.keySet()) {
                        processMapContentForValue(curContent.get(key),
                                mapValue, toResolvePath,
                                joinPath(curPath, key), toResolvePath, true,
                                splitArrayLeaf);
                    }
                    // } else if (index < 0) {
                } else if (isPathLeaf(toResolvePath)) {
                    // 路径的最后一级，不需要再取子元素递归查找
                    mapValue.put(joinPath(curPath, tmpToResolvePath),
                            childContent);
                } else {
                    // Including "/"
                    processMapContentForValue(
                            childContent,
                            mapValue,
                            null,
                            joinPath(curPath, curKey),
                            nextSeperatorIndex > 0 ? tmpToResolvePath
                                    .substring(nextSeperatorIndex) : null,
                            false, splitArrayLeaf);
                }

                // parent contains "//"
                if (allPathFlag) {
                    for (String key : curContent.keySet()) {
                        processMapContentForValue(curContent.get(key),
                                mapValue, orgPath, joinPath(curPath, key),
                                orgPath, true, splitArrayLeaf);
                    }
                }
            }
        } else if (isArray(content) && allPathFlag) {
            List<Object> tmpChildContent = getArray(content);

            for (int i = 0; i < tmpChildContent.size(); i++) {
                processMapContentForValue(tmpChildContent.get(i), mapValue,
                        orgPath, curPath + "[" + i + "]", toResolvePath, true,
                        splitArrayLeaf);
            }
        } else {
            // TODO
            // logger.debug("ERROR Message");
        }

        // return null;
    }

    /**
     * @param mapValue
     * @param curChildContent
     * @param arrayIndex
     * @param nextSeperatorIndex
     * @param allPathFlag
     * @param isAllPathBeginning
     * @param orgPath
     * @param toResolvePath
     * @param tmpToResolvePath
     * @param curPath
     * @param curKey
     * @param splitArrayLeaf
     */
    private static void processArrayContent(Map<String, Object> mapValue,
                                            List<Object> curChildContent, int arrayIndex,
                                            int nextSeperatorIndex, boolean allPathFlag,
                                            boolean isAllPathBeginning, String orgPath, String toResolvePath,
                                            String tmpToResolvePath, String curPath, String curKey,
                                            boolean splitArrayLeaf) {
        if (isAllPathBeginning) {
            // Beginning with "//"
            String tmpCurPath = joinPath(curPath, curKey) + "[" + arrayIndex
                    + "]";

            // 继续处理toResolvePath剩余的路径
            processMapContentForValue(
                    curChildContent.get(arrayIndex),
                    mapValue,
                    null,
                    tmpCurPath,
                    nextSeperatorIndex > 0 ? tmpToResolvePath
                            .substring(nextSeperatorIndex) : null, false,
                    splitArrayLeaf);

            // 再处理整个的toResolvePath
            processMapContentForValue(curChildContent.get(arrayIndex),
                    mapValue, toResolvePath, tmpCurPath, toResolvePath, true,
                    splitArrayLeaf);
            // } else if (index < 0) {
        } else if (!splitArrayLeaf && isPathLeaf(toResolvePath)) {
            // 路径的最后一级，不需要再取子元素递归查找
            // mapValue.put(joinPath(curPath, tmpToResolvePath) + "[" +
            // arrayIndex
            // + "]", curChildContent[arrayIndex]);
            mapValue.put(joinPath(curPath, tmpToResolvePath), curChildContent);
        } else {
            // Including "/"
            // 或者是路径的最后一级，并且需要把数组拆分成多项
            processMapContentForValue(
                    curChildContent.get(arrayIndex),
                    mapValue,
                    null,
                    joinPath(curPath, curKey) + "[" + arrayIndex + "]",
                    nextSeperatorIndex > 0 ? tmpToResolvePath
                            .substring(nextSeperatorIndex) : null, false,
                    splitArrayLeaf);
        }

        // parent contains "//"
        if (allPathFlag) {
            processMapContentForValue(curChildContent.get(arrayIndex),
                    mapValue, orgPath, joinPath(curPath, curKey) + "["
                            + arrayIndex + "]", orgPath, true, splitArrayLeaf);
        }
    }

    /**
     *
     * @param path
     * @return
     */
    // private static boolean isAbsolutePath(String path) {
    // if (StringUtils.isNotEmpty(path)) {
    // return path.indexOf(CommonConstant.ABSOLUTE_PATH_ROOT) == 0;
    // }
    //
    // return false;
    // }

    /**
     * @param path
     * @return
     */
    private static boolean isAllPath(String path) {
        if (StringUtils.isNotEmpty(path)) {
            return path.indexOf(CommonConstant.ABSOLUTE_PATH_ROOT) == 0;
        }

        return false;
    }

    /**
     * @param path
     * @return
     */
    public static String removeBeginningSeparator(String path) {
        if (StringUtils.isEmpty(path)) {
            return null;
        }

        int startIndex = 0;
        int pathLen = path.length();
        int seraratorLen = CommonConstant.KEY_SEPARATOR.length();

        while (startIndex < pathLen
                && path.indexOf(CommonConstant.KEY_SEPARATOR, startIndex) == startIndex) {
            startIndex += seraratorLen;
        }

        return path.substring(startIndex);
    }

    /**
     * @param path
     * @return
     */
    public static String removeEndingSeparator(String path) {
        if (StringUtils.isEmpty(path)) {
            return null;
        }

        int endIndex = path.length() - 1;
        int seraratorLen = CommonConstant.KEY_SEPARATOR.length();

        while (endIndex >= 0
                && path.lastIndexOf(CommonConstant.KEY_SEPARATOR, endIndex) == endIndex) {
            endIndex -= seraratorLen;
        }

        return path.substring(0, endIndex + 1);
    }

    /**
     * 取得路径中的索引值
     *
     * @param path
     * @return
     */
    private static int getArrayIndex(String path) {
        if (StringUtils.isNotEmpty(path)) {
            int beginIndex = path.lastIndexOf(CommonConstant.ARRAY_INDEX_BEGIN);
            int endIndex = path.lastIndexOf(CommonConstant.ARRAY_INDEX_END);
            if (endIndex > beginIndex && beginIndex >= 0) {
                return Integer.parseInt(path
                        .substring(beginIndex + 1, endIndex));
            }
        }

        return -1;
    }

    /**
     * @param parentPath
     * @param childPath
     * @return
     */
    public static String joinPath(String parentPath, String childPath) {
        if (StringUtils.isNotEmpty(childPath)) {
            return (StringUtils.isEmpty(parentPath) ? ""
                    : removeEndingSeparator(parentPath)
                    + CommonConstant.KEY_SEPARATOR)
                    + removeEndingSeparator(removeBeginningSeparator(childPath));
        }

        return (parentPath == null ? "" : parentPath);
    }

    /**
     * @param value
     * @return
     */
    public static boolean isArray(Object value) {
        if (value instanceof List) {
            return true;
        } else if (value != null && value.getClass().isArray()) {
            return true;
        }

        return false;
    }

    /**
     * @param map
     * @return
     */
    public static boolean isEmptyMap(Map<?, ?> map) {
        return map == null || map.isEmpty();
    }

    /**
     * @param value
     * @return
     */
    public static List<Object> getArray(Object value) {
        if (value instanceof List) {
            return (List<Object>) value;
        } else if (value != null && value.getClass().isArray()) {
            List<Object> ret = new ArrayList<Object>();
            for (Object obj : (Object[]) value) {
                ret.add(obj);
            }

            return ret;
        }

        return null;
    }

    /**
     * 生成结果Map中的所有key
     * <p>
     * 最后一级key对应的value为null或者空的Map，其余各级value都是Map.
     *
     * @param map          the map
     * @param path         the path
     * @param lastNullFlag the last null flag
     * @return true, if successful
     */
    public static boolean buildAllKeysForMap(Map<String, Object> map,
                                             String path, boolean lastNullFlag) {
        return addValueToMap(map, path, lastNullFlag ? null
                : new HashMap<String, Object>(), MapProcessType.ADD, null);
    }

    /**
     * @param map           返回数据在"/"对应的value中(为了对应顶层是数组，在外层封装了key为"/"的Map)
     * @param path
     * @param value
     * @param operationType 替换标识 true：替换map中path对应的值
     *                      false：仅创建map中对应的path，如果path不存在，使用value作为对应的值；否则保留path对应的值
     * @param arrayInfo     map中每一层数组的索引数据（如果对应层的数组没有索引，则对该层数组的所有元素进行操作）
     * @return
     */
    public static boolean addValueToMap(Map<String, Object> map, String path,
                                        Object value, MapProcessType operationType, MapArrayInfo arrayInfo) {
        if (StringUtils.isEmpty(path)) {
            return false;
        }

        path = MapUtil.removeBeginningSeparator(MapUtil
                .removeEndingSeparator(path));

        if (map != null) {
            path = StringUtils.isEmpty(path) ? ""
                    : CommonConstant.KEY_SEPARATOR + path;
            String[] splitPathArray = path.split(CommonConstant.KEY_SEPARATOR);
            splitPathArray[0] = CommonConstant.KEY_SEPARATOR;
            List<Map<String, Object>> parentMapList = new ArrayList<Map<String, Object>>();
            List<Map<String, Object>> tmpParentMapList = new ArrayList<Map<String, Object>>();
            parentMapList.add(map);

            for (int i = 0; i < splitPathArray.length; i++) {
                for (Map<String, Object> parentMap : parentMapList) {
                    Object curValue = parentMap.get(splitPathArray[i]);
                    // curValue = (curValue == null ? new HashMap<String,
                    // Object>()
                    // : curValue);

                    if (isArray(curValue)) {
                        if (operationType == MapProcessType.REINIT_ARRAY
                                && i == splitPathArray.length - 1) {
                            // Map对应层初始化为数组 && 路径最后一级
                            continue;
                        }

                        // 必须是List
                        List<Object> curValueList = (List<Object>) curValue;

                        if (curValueList != null) {
                            // 定位索引值
                            int index = getPathIndex(splitPathArray, i,
                                    arrayInfo);

                            if (index >= 0) {
                                if (index > curValueList.size()) {
                                    // logger.error("Array Index Out Of Bounds.");
                                    // throw new
                                    // Exception("Array Index Out Of Bounds.");
                                } else {
                                    if (index == curValueList.size()) {
                                        curValueList.add(null);
                                    }

                                    processArrayInfo(splitPathArray, i,
                                            curValueList, index, value,
                                            operationType, tmpParentMapList);
                                }
                            } else {
                                for (int j = 0; j < curValueList.size(); j++) {
                                    processArrayInfo(splitPathArray, i,
                                            curValueList, j, value,
                                            operationType, tmpParentMapList);
                                }
                            }
                        }
                        /*
                         * else { // logger.error("Error!"); }
                         */
                    } else if (curValue instanceof Map) {
                        // Map类型
                        // tmpParentMapList.add((Map<String, Object>) curValue);
                        // parentMap
                        // .put(splitPathArray[i],
                        // (i == splitPathArray.length - 1
                        // && curValue == null ? value
                        // : curValue));
                        if (i == splitPathArray.length - 1) {
                            // 最后一级path
                            if (operationType == MapProcessType.REPLACE) {
                                // 替换标识
                                parentMap.put(splitPathArray[i], value);
                            } else if (operationType == MapProcessType.REINIT_ARRAY) {
                                // TODO
                                // 保存对应值，对数组中的每个元素添加保存的值
                                Map<String, Object> reservedValue = new HashMap<String, Object>();
                                reservedValue.put(splitPathArray[i], curValue);
                                parentMap
                                        .put(RESERVED_MAP_VALUE, reservedValue);
                                parentMap.put(splitPathArray[i], value);
                            }
                            // 非替换(已经有值(Map类型))，保持原来的值
                        } else {
                            // 不是最后一级path
                            // 已经有值(Map)，保持原来的值
                            // parentMap.put(splitPathArray[i], value);
                            tmpParentMapList
                                    .add((Map<String, Object>) curValue);
                        }
                    } else {
                        // 其它类型
                        if (i == splitPathArray.length - 1) {
                            if (operationType == MapProcessType.REINIT_ARRAY) {
                                parentMap.put(splitPathArray[i], value);
                            } else {
                                // 覆盖原来的数据
                                parentMap.put(splitPathArray[i], value);
                            }
                        } else {
                            // 不是最后一级path，用Map覆盖原来的数据，使得可以继续构造路径
                            Map<String, Object> newValue = new HashMap<String, Object>();
                            parentMap.put(splitPathArray[i], newValue);
                            tmpParentMapList.add(newValue);
                        }
                    }
                }

                parentMapList.clear();
                parentMapList.addAll(tmpParentMapList);
                tmpParentMapList.clear();
            }

            return true;
        }

        return false;
    }

    public static void mergeReservedValue(Map<String, Object> map) {
        if (map != null) {
            if (map.containsKey(RESERVED_MAP_VALUE)) {
                // 合并已保存的内容
                Map<String, Object> reservedValue = (Map<String, Object>) map
                        .get(RESERVED_MAP_VALUE);
                map.remove(RESERVED_MAP_VALUE);

                for (Entry<String, Object> entry : reservedValue.entrySet()) {
                    String key = entry.getKey();
                    Map<String, Object> value = (Map<String, Object>) entry
                            .getValue();
                    List<Map<String, Object>> list = (List<Map<String, Object>>) map
                            .get(key);

                    for (Map<String, Object> element : list) {
                        mergeMaps(value, element);
                    }
                }
            }

            // 处理所有的子元素
            for (Entry<String, Object> entry : map.entrySet()) {
                Object value = entry.getValue();

                if (value instanceof Map) {
                    mergeReservedValue((Map<String, Object>) value);
                } else if (isArray(value)) {
                    List<Object> valueList = (List<Object>) value;

                    for (Object element : valueList) {
                        if (element instanceof Map) {
                            mergeReservedValue((Map<String, Object>) element);
                        } else if (isArray(element)) {
                            // 数组的每一个元素不能是数组
                            // logger.error("Error");
                            // throw new Exception("Error");
                        }
                    }
                }
            }
        }
    }

    /**
     * 合并2个Map的数据。目前只支持从源Map拷贝数据到目的Map；如果源Map和目的Map各有一部分数据(数组中的数据)，没有完全合并
     *
     * @param src the src
     * @param dst the dst
     */
    private static void mergeMaps(Map<String, Object> src,
                                  Map<String, Object> dst) {
        if (src != null && dst != null) {
            for (Entry<String, Object> entry : src.entrySet()) {
                String key = entry.getKey();
                Object srcValue = entry.getValue();

                if (dst.containsKey(key)) {
                    Object dstValue = dst.get(key);

                    if (srcValue instanceof Map && dstValue instanceof Map) {
                        mergeMaps((Map<String, Object>) srcValue,
                                (Map<String, Object>) dstValue);
                    } else if (isArray(dstValue)) {
                        List<Object> dstValueList = (List<Object>) dstValue;

                        if (isArray(srcValue)) {
                            // TODO
                            // 需要src、dst中的每一个元素的属性互相拷贝，如果有重复的项，保留dst的内容
                            // 添加到List
                            dstValueList.addAll((List<Object>) srcValue);
                        } else if (srcValue instanceof Map) {
                            for (Object dstElement : dstValueList) {
                                if (dstElement instanceof Map) {
                                    mergeMaps((Map<String, Object>) srcValue,
                                            (Map<String, Object>) dstElement);
                                }
                            }
                        } else {
                            // 其它数据类型，不处理
                        }
                    } else {
                        // TODO
                        // 其它类型的数据需要
                    }
                } else {
                    dst.put(key, srcValue);
                }
            }
        }
    }

    /**
     * 获取Map的对应路径的数组最大索引值
     *
     * @param map       the map
     * @param path      the path
     * @param arrayInfo the array info
     * @return the array last index
     */
    public static int getLastIndexByPath(Map<String, Object> map, String path,
                                         MapArrayInfo arrayInfo) {
        if (map != null && StringUtils.isNotEmpty(path)) {

            path = MapUtil.removeBeginningSeparator(MapUtil
                    .removeEndingSeparator(path));

            if (map != null) {
                path = StringUtils.isEmpty(path) ? ""
                        : CommonConstant.KEY_SEPARATOR + path;
                String[] splitPathArray = path
                        .split(CommonConstant.KEY_SEPARATOR);
                splitPathArray[0] = CommonConstant.KEY_SEPARATOR;
                Object curObj = map;

                for (int i = 0; curObj != null && i < splitPathArray.length; i++) {
                    Map<String, Object> curMap = (Map<String, Object>) curObj;

                    if (curMap != null) {
                        Object curValue = curMap.get(splitPathArray[i]);

                        if (curValue instanceof Map) {
                            curObj = curValue;
                        } else if (isArray(curValue)) {
                            if (i == splitPathArray.length - 1) {
                                curObj = curValue;
                                break;
                            }

                            int index = getPathIndex(splitPathArray, i,
                                    arrayInfo);

                            if (index < 0) {
                                index = 0;
                            }

                            List curList = (List<Object>) curValue;

                            if (curList.size() > index) {
                                curObj = curList.get(index);
                            } else {
                                curObj = null;
                            }
                        } else {
                            curObj = null;
                        }
                    } else {
                        curObj = null;
                    }
                }

                if (isArray(curObj)) {
                    return ((List<Object>) curObj).size() - 1;
                }
            }
        }

        return -1;
    }

    /**
     * 获取对应路径在ArrayInfo中的数据，如果有对应的路径，返回该路径对应的索引值
     *
     * @param splitPathArray the split path array
     * @param endLevelIndex  the index
     * @param arrayInfo      the array info
     * @return the array info index
     */
    private static int getPathIndex(String[] splitPathArray, int endLevelIndex,
                                    MapArrayInfo arrayInfo) {
        if (splitPathArray != null && endLevelIndex < splitPathArray.length
                && arrayInfo != null) {
            StringBuffer path = new StringBuffer();

            for (int i = 0; i <= endLevelIndex; i++) {
                path.append(splitPathArray[i]).append(
                        CommonConstant.KEY_SEPARATOR);
            }

            if (path.length() > 0) {
                path.deleteCharAt(path.length() - 1);
            }

            String curPath = !CommonConstant.KEY_SEPARATOR.equals(path
                    .toString()) ? removeEndingSeparator(removeBeginningSeparator(path
                    .toString())) : path.toString();

            if (StringUtils.isEmpty(curPath)) {
                return -1;
            }

            List<Pair<String, Integer>> pathList = arrayInfo.getPaths();

            for (Pair<String, Integer> pair : pathList) {
                if (curPath.equals(pair.getKey())
                        || curPath
                        .equals(removeEndingSeparator(removeBeginningSeparator(pair
                                .getKey())))) {
                    return pair.getValue();
                }
            }
        }

        return -1;
    }

    /**
     * 处理Map中的数组数据
     *
     * @param splitPathArray the split path array
     * @param pathIndex      the path index
     * @param curValueList   the cur value list
     * @param valueIndex     the value index
     * @param value          the value
     * @param operationType  the operation type
     * @param parentMapList  the parent map list
     */
    private static void processArrayInfo(String[] splitPathArray,
                                         int pathIndex, List<Object> curValueList, int valueIndex,
                                         Object value, MapProcessType operationType,
                                         List<Map<String, Object>> parentMapList) {
        Object element = curValueList.get(valueIndex);
        // (不是数组类型－-模型定义中数组的每一个元素不能是数组)

        if (pathIndex == splitPathArray.length - 1) {
            // 最后一级path
            if (!(element instanceof Map)
                    || operationType == MapProcessType.REPLACE) {
                if (isArray(value)) {
                    // TODO
                    // throw new
                    // Exception("数组的每一个元素不能是数组");
                }

                // 覆盖原来的数据
                curValueList.set(valueIndex, value);
            } else {
                // 保持原来的值
            }
        } else {
            // 不是最后一级path
            if (element instanceof Map) {
                parentMapList.add((Map<String, Object>) element);
            } else {
                if (isArray(value)) {
                    // TODO
                    // throw new
                    // Exception("数组的每一个元素不能是数组");
                }

                // 其它类型 ：用Map覆盖原来的数据，使得可以继续构造路径
                Map<String, Object> newValue = new HashMap<String, Object>();
                curValueList.set(valueIndex, newValue);
                parentMapList.add(newValue);
            }
        }
    }

    /**
     * 是否为路径的最后一级，以下形式的路径返回true
     * <p>
     * path
     * <p>
     * /path
     * <p>
     * path/
     * <p>
     * /path/
     *
     * @param path
     * @return
     */
    private static boolean isPathLeaf(String path) {
        String tmpPath = removeEndingSeparator(removeBeginningSeparator(path));

        if (StringUtils.isNotEmpty(tmpPath)) {
            return tmpPath.indexOf(CommonConstant.KEY_SEPARATOR) < 0;
        }

        return false;
    }

    /**
     * The Enum MessageFilterType.
     */
    // public enum MessageFilterType {
    // // 数组
    // ARRAY,
    // // 数组之外的
    // EXCEPT_ARRAY,
    // // 所有的
    // BOTH;
    //
    // private MessageFilterType() {
    // }
    //
    // public boolean isProcessingArray() {
    // return this == ARRAY || this == BOTH;
    // }
    //
    // public boolean isProcessingExceptArray() {
    // return this == EXCEPT_ARRAY || this == BOTH;
    // }
    // }
}
